package cn.sjx.modules.nbiot.entity.receive;

import cn.hutool.core.util.StrUtil;
import io.netty.buffer.ByteBuf;
import lombok.Getter;

/**
 * 普通接收报文 基类（0x20/0x21）
 *
 * @Author: sjx
 * @Date: 2019年08月30日 0030 13:44:25
 */
@Getter
public abstract class IotProtocolReceiveBase extends ReceiveBase {

    /**
     * <p>
     * 字段名称：版本
     * 说明：
     * 高字节代表：软件版本号；
     * 低字节：从高到低分别代表；
     * 7~6位：预留；
     * 5~3位：协议类型（000: UDP、001:TCP）
     * 2~1位：运营商类型（电信：00 移动：01 联通：10）；
     * 0位：有无心跳（1为有 0无）
     * <p>
     * 举个例子：
     * 收到数据：0E03
     * 转为二进制：111000000011
     * <p>
     * 1110       00      000     01       1
     * 版本号：14   预留     UDP     移动   有心跳
     * 字节：2
     * </p>
     */
    protected short version;

    /**
     * <p>
     * 字段名称：预留字段2
     * 说明：预留字段
     * 字节：2
     * </p>
     */
    protected short reserverd2;

    /**
     * <p>
     * 字段名称：校验码
     * 说明：CRC16
     * 字节：2
     * </p>
     */
    protected short crcCode;

    // region ========================= 扩展字段，由版本号解析而得 =========================

    /**
     * 有无心跳
     * 1：有；0：无
     */
    private String heartBeat;

    /**
     * 运营商类型
     * 00:电信；01：移动；10：联通
     */
    private String operator;

    /**
     * 协议类型
     * 000：UDP；001:TCP
     */
    private String agreementType;

    /**
     * 程序版本
     */
    private String programVersion;

    // end region ==========================================================================

    /**
     * 基本数据解码实现
     */
    @Override
    public void decode(ByteBuf buf) {
        // 获取协议类型
        this.type = buf.readByte();

        // 获取版本号
        this.version = buf.readShort();

        // 自定义解码
        decodeImpl(buf);

        // 获取预留字段2
        this.reserverd2 = buf.readShort();

        // 获取校验码
        this.crcCode = buf.readShort();

        // 解析版本信息
        analysisVersion(version);
    }

    /**
     * 解析版本信息
     *
     * @param version
     */
    private void analysisVersion(short version) {
        if (version != 0) {
            StringBuilder tempSb = new StringBuilder(Integer.toBinaryString(version));
            int len = tempSb.length();
            if (len < 16) {
                for (int i = 0; i < 16 - len; i++) {
                    tempSb.insert(0, '0');
                }
            }

            // 截取字段
            tempSb = tempSb.reverse();
            String heartBeatStr = StrUtil.reverse(tempSb.substring(0, 1));
            String operatorStr = StrUtil.reverse(tempSb.substring(1, 3));
            String agreementTypeStr = StrUtil.reverse(tempSb.substring(3, 6));
            String programVersionStr = StrUtil.reverse(tempSb.substring(8, 16));

            // 设值
            this.heartBeat = StrUtil.equals(heartBeatStr, "0") ? "无心跳" : "有心跳";
            this.operator = StrUtil.equals(operatorStr, "00") ? "中国电信" : (StrUtil.equals(operatorStr, "01") ? "中国移动" : "中国联通");
            this.agreementType = StrUtil.equals(agreementTypeStr, "000") ? "UDP" : "TCP";
            this.programVersion = Integer.valueOf(programVersionStr, 2).toString();
        }
    }

}
